package com.lct.simpleforecast.ui.activity.base

import android.annotation.TargetApi
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.support.v7.graphics.drawable.DrawerArrowDrawable
import android.support.v7.widget.Toolbar
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import com.afollestad.materialdialogs.MaterialDialog
import com.lct.simpleforecast.ActivityManager
import com.lct.simpleforecast.MyApplication
import com.lct.simpleforecast.R
import com.lct.simpleforecast.extensions.ctx
import com.lct.simpleforecast.receiver.NetworkBroadcastReceiver
import com.lct.simpleforecast.ui.activity.AboutActivity
import com.lct.simpleforecast.ui.activity.SettingActivity
import com.lct.simpleforecast.ui.custom.LoadingView
import org.jetbrains.anko.find
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.toast
import kotlin.properties.Delegates

/**
 * Author：SkySmile
 * Date：2018/7/4
 * Description：Activity基类，主要封装的有以下功能：
 * 1.运行时权限申请
 * 2.页面加载loading
 * 3.toolbar
 * 4.监听网络状态变化
 */
abstract class BaseActivity : AppCompatActivity(), NetworkBroadcastReceiver.NetworkChange {
    private lateinit var afterPermissionGranted: () -> Unit
    private var isToSettingPermission = false
    private val loadingView: LoadingView by lazy { LoadingView(MyApplication.instance) }
    //toolbar可空，因为有的页面不需要toolbar
    protected val toolbar: Toolbar? by lazy { findViewById<Toolbar?>(R.id.toolbar) }
    private var networkBroadcastReceiver: NetworkBroadcastReceiver by Delegates.notNull()
    //网络错误页面是否正在显示
    private var isShowingNetworkErrorView = false

    companion object {
        private const val REQUEST_PERMISSION_CODE = 100
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(setLayoutResId())
        ActivityManager.instance.addActivity(this)
        addLoadingView()
        initData()
        initListener()
    }

    override fun onResume() {
        super.onResume()
        //注册监听网络状态的广播，每次注册都会首先调用一次广播的onReceive方法
        networkBroadcastReceiver = NetworkBroadcastReceiver(this)
        val intentFilter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
        registerReceiver(networkBroadcastReceiver, intentFilter)
        //如果用户拒绝了权限之后，又通过点击设置去设置权限，返回时回调afterSettingPermissions方法
        if (isToSettingPermission) {
            isToSettingPermission = false
            afterSettingPermissions()
        }
    }

    override fun onPause() {
        super.onPause()
        //注销广播，onPause方法在Activity页面关闭的时候一定会被调用
        unregisterReceiver(networkBroadcastReceiver)
    }

    override fun onDestroy() {
        super.onDestroy()
        ActivityManager.instance.removeActivity(this)
    }

    /**
     * 设置activity的布局
     */
    protected abstract fun setLayoutResId(): Int

    /**
     * 初始化数据
     */
    protected abstract fun initData()

    /**
     * 设置控件的事件监听，子类根据需要进行重写
     */
    protected open fun initListener() {}

    /**
     * 网络发生变化
     */
    override fun onNetworkChange() {
        if (MyApplication.instance.isNetworkAvailable() && isShowingNetworkErrorView) {
            //网络变为可用并且正在显示的页面是错误页面
            isShowingNetworkErrorView = false
            afterNetworkAvailable()
        }
    }

    /**
     * 网络由不可用变为可用后执行的操作
     * 这样做为了设置过权限之后，能及时执行响应的操作，不需要的子类可以不重写
     */
    protected open fun afterNetworkAvailable() {}

    /**
     * 申请的运行时权限被禁止，点击设置进入权限设置页面，然后返回到本页面时的回调
     * 这样做为了设置过权限之后，能及时执行响应的操作，不需要的子类可以不重写
     *
     * 运行时权限尽量不要在onResume方法中申请，如果用户拒绝的话会一直循环弹框提示。
     * 因为调用Activity的requestPermissions方法，权限被拒绝之后，会回调到onResume方法。
     *
     */
    protected open fun afterSettingPermissions() {}

    /**
     * 设置页面加载时的loading
     */
    private fun addLoadingView() {
        //设置背景色
        loadingView.setBackgroundColor(ContextCompat.getColor(this,
                R.color.colorLayoutDefaultBg))
        //设置第二个圆的颜色
        loadingView.loadingSecondColor = ContextCompat.getColor(this, R.color.colorPrimary)
        //默认隐藏，这样不需要加载loading的页面不用调用hideLoading方法
        loadingView.visibility = View.GONE
        //宽高充满屏幕
        val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT)
        //添加到根布局
        val rootView = window.decorView.find<ViewGroup>(android.R.id.content)
        rootView.addView(loadingView, params)
        //有toolbar的时候，设置marginTop，显示出来toolbar
        toolbar?.let {
            val marginParams = loadingView.layoutParams as ViewGroup.MarginLayoutParams
            marginParams.setMargins(0, getActionBarHeight(), 0, 0)
            loadingView.layoutParams = marginParams
        }
    }

    /**
     * 获取ActionBar的高度，Toolbar的高度和ActionBar的高度是一样的
     */
    private fun getActionBarHeight(): Int {
        var actionBarHeight = 0
        val typedValue = TypedValue()
        if (theme.resolveAttribute(android.R.attr.actionBarSize, typedValue, true)) {
            actionBarHeight = TypedValue.complexToDimensionPixelSize(typedValue.data,
                    resources.displayMetrics)
        }
        return actionBarHeight
    }

    /**
     * 显示加载中的loading
     */
    protected fun showLoadingView(loadingText: String = resources.getString(R.string.loading)) {
        loadingView.loadingText = loadingText
        loadingView.showLoading()
    }

    /**
     * 隐藏加载loading
     */
    protected fun hideLoadingView() {
        loadingView.hideLoading()
    }

    /**
     * 显示加载失败的loading
     */
    protected fun showLoadingFailView(
            loadingFailText: String = resources.getString(R.string.loading_fail),
            loadingFailImage: Int = R.drawable.img_loading_fail,
            doOnClick: () -> Unit = {}) {
        loadingView.loadingFailText = loadingFailText
        loadingView.loadingFailImage = BitmapFactory.decodeResource(resources, loadingFailImage)
        loadingView.showLoadingFail(doOnClick)
    }

    /**
     * 显示网络不可用的View，点击跳转到网络设置界面
     */
    protected fun showNetworkErrorView(
            networkErrorText: String = resources.getString(R.string.network_error_to_check),
            networkErrorImage: Int = R.drawable.img_network_error) {
        isShowingNetworkErrorView = true
        loadingView.loadingFailText = networkErrorText
        loadingView.loadingFailImage = BitmapFactory.decodeResource(resources, networkErrorImage)
        loadingView.showLoadingFail {
            //打开网络设置页面
            startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
        }
    }

    /**
     * 申请运行时权限权限，在申请之前先检查是否已经授权，没有授权再进行申请
     *
     * @param permissions 申请的权限
     * @param doAction 权限全部授权后执行的操作
     */
    @TargetApi(Build.VERSION_CODES.M)
    protected fun requestPermissions(permissions: Array<String>, doAction: () -> Unit) {
        afterPermissionGranted = doAction
        if (checkPermissionAllGranted(permissions)) {
            afterPermissionGranted()
        } else {
            requestPermissions(permissions, REQUEST_PERMISSION_CODE)
        }
    }

    /**
     * 检查申请的运行时权限是否全部授权
     *
     * @param permissions 申请的权限
     * @return false | true
     */
    private fun checkPermissionAllGranted(permissions: Array<String>): Boolean {
        return permissions.all {
            (ContextCompat.checkSelfPermission(this, it)
                    == PackageManager.PERMISSION_GRANTED)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
                                            grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_PERMISSION_CODE) {
            val isHasDenied = grantResults.any { it != PackageManager.PERMISSION_GRANTED }
            if (isHasDenied) {
                //部分权限没有被授权，给出提示
                showMissingPermissionDialog()
            } else {
                //申请的权限全部被授权，执行需要的操作
                afterPermissionGranted()
            }
        }
    }

    private fun showMissingPermissionDialog() {
        MaterialDialog.Builder(this)
                .title(R.string.dialog_title)
                .content(R.string.dialog_missing_permission_content)
                .negativeText(R.string.cancel)
                .positiveText(R.string.set)
                .onPositive { _, _ -> openAppSettings() }
                .build()
                .show()
    }

    /**
     * 打开应用的设置界面
     */
    private fun openAppSettings() {
        isToSettingPermission = true
        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
        intent.data = Uri.parse("package:$packageName")
        startActivity(intent)
    }

    /**
     * 初始化toolbar菜单并设置点击事件
     */
    protected fun initToolbarMenu() {
        toolbar?.inflateMenu(R.menu.menu_main)
        toolbar?.setOnMenuItemClickListener {
            when (it.itemId) {
                R.id.action_settings -> startActivity<SettingActivity>()
                R.id.action_about -> startActivity<AboutActivity>()
                else -> toast("Unknown option")
            }
            true
        }
    }

    /**
     * 开启toolbar上面的导航icon，设置一个箭头的icon并设置被按压时的触发事件，
     * 默认关闭当前页面
     */
    protected fun enableHomeAsUp(onClick: () -> Unit = { finish() }) {
        toolbar?.navigationIcon = createUpDrawable()
        toolbar?.setNavigationOnClickListener { onClick() }
    }

    /**
     * 生成一个箭头icon
     * DrawerArrowDrawable是一个可以绘制三条横线或者箭头,并且在两者之间添加过渡动画的Drawable实例.
     * 通过调用{@link DrawerArrowDrawable#setProgress(float)}方法来设置横线到箭头的进度值.
     * 0f是三条横线
     * 1f是箭头
     */
    private fun createUpDrawable() = DrawerArrowDrawable(toolbar?.ctx).apply { progress = 1f }

}